#include <stdio.h>
#include <string.h>

#include "check.h"
#include "security_common.h"

#define ZERO_PADDING_BLOCK_SIZE 8

// 八字节零填充
START_TEST(padding_zero_ok) {
    int ret = 0;
    char src1[] = "123";
    char src2[] = "12345678";
    char ans1[8] = {'1', '2', '3'};
    char ans2[16] = {'1', '2', '3', '4', '5', '6', '7', '8'};
    char out1[32] = { 0 };
    char out2[32] = { 0 };
    size_t len1, len2;
    char unpadding1[32] = { 0 }, unpadding2[32] = { 0 };

    ret = padding_zero(out1, &len1, sizeof(out1), src1, strlen(src1));
    ck_assert_int_eq(ret, INTERNAL_SECURITY_OK);
    ret = padding_zero(out2, &len2, sizeof(out2), src2, strlen(src2));
    ck_assert_int_eq(ret, INTERNAL_SECURITY_OK);

    ck_assert_int_eq(len1, ZERO_PADDING_BLOCK_SIZE);
    ck_assert_int_eq(len2, ZERO_PADDING_BLOCK_SIZE * 2);

    ck_assert_mem_eq(out1, ans1, ZERO_PADDING_BLOCK_SIZE);
    ck_assert_mem_eq(out2, ans2, ZERO_PADDING_BLOCK_SIZE * 2);

    ret = unpadding_zero(unpadding1, &len1, sizeof(unpadding1), out1, len1);
    ck_assert_int_eq(ret, INTERNAL_SECURITY_OK);
    ret = unpadding_zero(unpadding2, &len2, sizeof(unpadding2), out2, len2);
    ck_assert_int_eq(ret, INTERNAL_SECURITY_OK);

    ck_assert_int_eq(len1, strlen(src1));
    ck_assert_int_eq(len2, strlen(src2));

    ck_assert_mem_eq(unpadding1, src1, strlen(src1));
    ck_assert_mem_eq(unpadding2, src2, strlen(src2));
}
END_TEST

START_TEST(padding_zero_input) {
    char out[1024] = { 0 };
    size_t olen = 0;
    char in[] = "123";
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, padding_zero(NULL, &olen, sizeof(out), in, strlen(in)));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, padding_zero(out, NULL, sizeof(out), in, strlen(in)));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, padding_zero(out, &olen, 0, in, strlen(in)));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, padding_zero(out, &olen, sizeof(out), NULL, strlen(in)));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, padding_zero(out, &olen, sizeof(out), in, 0));

    ck_assert_int_eq(INTERNAL_SECURITY_PADDING_BUFFER_TOO_SMALL, padding_zero(out, &olen, 1, in, strlen(in)));


    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, unpadding_zero(NULL, &olen, sizeof(out), in, strlen(in)));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, unpadding_zero(out, NULL, sizeof(out), in, strlen(in)));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, unpadding_zero(out, &olen, 0, in, strlen(in)));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, unpadding_zero(out, &olen, sizeof(out), NULL, strlen(in)));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, unpadding_zero(out, &olen, sizeof(out), in, 0));

    ck_assert_int_eq(INTERNAL_SECURITY_PADDING_BUFFER_TOO_SMALL, unpadding_zero(out, &olen, 1, in, strlen(in)));
}
END_TEST

// pkcs7填充
START_TEST(padding_pkcs7_ok) {
    int ret = 0;
    char src1[] = "123";
    char src2[] = "12345678";
    char ans1[8] = {'1', '2', '3', 1};
    char ans2[16] = {'1', '2', '3', '4', '5', '6', '7', '8', 4, 4, 4, 4};
    char out1[32] = { 0 };
    char out2[32] = { 0 };
    size_t len1, len2;
    char unpadding1[32] = { 0 }, unpadding2[32] = { 0 };
    size_t block_size = 4;

    ret = padding_pkcs7(out1, &len1, sizeof(out1), src1, strlen(src1), block_size);
    ck_assert_int_eq(ret, INTERNAL_SECURITY_OK);
    ret = padding_pkcs7(out2, &len2, sizeof(out2), src2, strlen(src2), block_size);
    ck_assert_int_eq(ret, INTERNAL_SECURITY_OK);

    ck_assert_int_eq(len1, block_size);
    ck_assert_int_eq(len2, block_size * 3);

    ck_assert_mem_eq(out1, ans1, ZERO_PADDING_BLOCK_SIZE);
    ck_assert_mem_eq(out2, ans2, ZERO_PADDING_BLOCK_SIZE * 2);

    ret = unpadding_pkcs7(unpadding1, &len1, sizeof(unpadding1), out1, len1);
    ck_assert_int_eq(ret, INTERNAL_SECURITY_OK);
    ret = unpadding_pkcs7(unpadding2, &len2, sizeof(unpadding2), out2, len2);
    ck_assert_int_eq(ret, INTERNAL_SECURITY_OK);

    ck_assert_int_eq(len1, strlen(src1));
    ck_assert_int_eq(len2, strlen(src2));

    ck_assert_mem_eq(unpadding1, src1, strlen(src1));
    ck_assert_mem_eq(unpadding2, src2, strlen(src2));
}
END_TEST

START_TEST(padding_pkcs7_input) {
    char out[1024] = { 0 };
    size_t olen = 0;
    char in[] = "123";
    size_t block_size = 10;
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, padding_pkcs7(NULL, &olen, sizeof(out), in, strlen(in), block_size));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, padding_pkcs7(out, NULL, sizeof(out), in, strlen(in), block_size));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, padding_pkcs7(out, &olen, 0, in, strlen(in), block_size));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, padding_pkcs7(out, &olen, sizeof(out), NULL, strlen(in), block_size));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, padding_pkcs7(out, &olen, sizeof(out), in, 0, block_size));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, padding_pkcs7(out, &olen, sizeof(out), in, strlen(in), 0));

    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, padding_pkcs7(out, &olen, 0, in, strlen(in), block_size));

    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, unpadding_pkcs7(NULL, &olen, sizeof(out), in, strlen(in)));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, unpadding_pkcs7(out, NULL, sizeof(out), in, strlen(in)));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, unpadding_pkcs7(out, &olen, 0, in, strlen(in)));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, unpadding_pkcs7(out, &olen, sizeof(out), NULL, strlen(in)));
    ck_assert_int_eq(INTERNAL_SECURITY_BAD_INPUT, unpadding_pkcs7(out, &olen, sizeof(out), in, 0));

    ck_assert_int_eq(INTERNAL_SECURITY_PADDING_BUFFER_TOO_SMALL, unpadding_pkcs7(out, &olen, 1, in, strlen(in)));
}
END_TEST

Suite *check_common(void)
{
    Suite *s;
    TCase *tc_core;

    s = suite_create("common test");

    tc_core = tcase_create("core");
    tcase_add_test(tc_core, padding_zero_ok);
    tcase_add_test(tc_core, padding_zero_input);
    tcase_add_test(tc_core, padding_pkcs7_ok);
    tcase_add_test(tc_core, padding_pkcs7_input);

    suite_add_tcase(s, tc_core);

    return s;
}